<template>
  <div class="goods-sku">
    <dl v-for="item in goods.specs" :key="item.id">
      <dt>{{item.name}}</dt>
      <dd>
        <template v-for="value in item.values" :key="value.name">
          <img :class="{selected: value.selected, disabled: value.disabled}" @click="btnClick(value, item.values)" v-if="value.picture" :src="value.picture" alt="">
          <span :class="{selected: value.selected, disabled: value.disabled}" @click="btnClick(value, item.values)" v-else>{{value.name}}</span>
        </template>
      </dd>
    </dl>
  </div>
</template>
<script>
import powset from '@/vendor/power-set'
const spliter = '⭐️'
// 根据skus去造一个字典 (处理数据)
const getPathMap = (skus) => {
  // 返回的就是这个字典
  const pathMap = {}
  skus.forEach(sku => {
    // 1. 筛选有库存的 根据 sku.inventory来筛选 库存大于0 才去处理
    if (sku.inventory) {
      // console.log('有效的sku', sku)
      // 2. 将sku中 specs数组处理成算法需要的数据 ['蓝色', '20cm', '中国']
      const specs = sku.specs.map(spec => spec.valueName)
      // console.log('specs', specs)
      // 3. 利用算法求出每一个sku的子集 处理成 ['蓝色'] ['20cm'] ['中国'] ['蓝色', '20cm'] .......
      const powerSetArr = powset(specs)
      // console.log('powerSetArr', powerSetArr)
      // 4. 遍历一下子集数组 ,给每一个子集处理成字符串∂
      powerSetArr.forEach(set => {
        const key = set.join(spliter)
        // console.log('key', key)
        // pathMap刚开始是个 {} 如果没有该属性
        // 遍历第一个sku子集 找 pathMap['黑色'] 是一个undefined 所以进入else
        // 遍历第二个sku子集 找 pathMap['黑色']的时候  已经有值了  所以直接把当前sku的id push进来
        // 有重复的key值 直接把当前的sku.id push进去   没有重复的就新建一个数组把当前sku.id push进去
        // pathMap = {a: '我是a'}   pathMap.b = ['111']  pathMap.b.push('222')
        // pathMap = {a: '我是a', b: ['111','222']}
        // let key = 'c'  pathMap[key] ===>  pathMap.c  pathMap[key] = ['111']  pathMap[key].push('333')
        // pathMap = {a: '我是a', b: ['111','222'], c: ['111', '333']}
        // key值是: '黑色' ''  '20cm'  '中国'   '中国⭐️20cm'
        if (pathMap[key]) {
          pathMap[key].push(sku.id)
          // console.log('非第一次加入', pathMap)
        } else {
          // 赋值了一个空数组 然后里面push一项id pathMap[key] = [sku.id] 相当于 pathMap[key] = []  pathMap[key].push(sku.id)
          pathMap[key] = [sku.id]
          // console.log('第一次加入', pathMap)
        }
      })
    }
  })

  return pathMap
}

// 更新按钮禁用状态
const updateDisabledStatus = (pathMap, specs) => {
  // 备份一下现在已经选中的按钮
  const selectedJSON = JSON.stringify(getSelectedSpec(specs))
  console.log('顺序数组', selectedJSON)
  specs.forEach((spec, index) => {
    // spec是每一行的按钮
    spec.values.forEach(btn => {
      // btn 就是每一个按钮
      // 拿已经选中的按钮 跟下一次可能会点击的按钮进行组合 然后判断组合之后的key值在不在pathMap里
      // 如果在当前的btn按钮就可以选中,如果组合不在pathMap里就需要给当前的btn 禁用
      const selectedBtnArr = JSON.parse(selectedJSON)
      // 通过遍历拼接所有下一次可能点击按钮
      selectedBtnArr[index] = btn.name
      // console.log('selectedBtnArr', selectedBtnArr)
      // 转成字符串key值,看是否在pathMap里
      const key = selectedBtnArr.filter(v => v).join(spliter)
      // console.log('key', key)
      // 判断按钮的组合路径在不在pathMap里,如果不在就禁用 pathMap.a 相当于 let key = 'a'  pathMap[key]
      if (pathMap[key]) {
        btn.disabled = false
      } else {
        btn.disabled = true
      }
    })
  })
}

// 按顺序获取选中路径
const getSelectedSpec = (specs) => {
  const arr = []
  specs.forEach((spec, index) => {
    // 找出每一行选中的那一项
    const btn = spec.values.find(item => item.selected)
    if (btn) {
      arr[index] = btn.name
    } else {
      arr[index] = undefined
    }
  })
  return arr
}

// 还原默认选中项
const initDefaultSelected = (goods, skuId) => {
  // 根据skuId 去找到具体的sku
  const sku = goods.skus.find(item => item.id === skuId)
  // 如果找不到这个sku 就拉倒退出
  if (!sku) return
  // 通过遍历按钮的数组去给选中的按钮加上selected = true 属性
  console.log('sku', sku)
  goods.specs.forEach((spec, index) => {
    spec.values.forEach(btn => {
      console.log('sku里的按钮', sku.specs[index].valueName)
      btn.selected = btn.name === sku.specs[index].valueName
    })
  })
}
export default {
  name: 'GoodsSku',
  props: {
    goods: {
      type: Object,
      default () {
        return {
          skus: [],
          specs: []
        }
      }
    },
    skuId: {
      type: String,
      default: ''
    }
  },
  setup (props, context) {
    // 当传入skuId 的时候,需要还原一下点中的按钮
    if (props.skuId) {
      initDefaultSelected(props.goods, props.skuId)
    }
    // 测试幂集算法
    // console.log(powset(['蓝色', '20cm', '中国']))
    const pathMap = getPathMap(props.goods.skus)
    // 初始化的时候更新按钮禁用状态
    updateDisabledStatus(pathMap, props.goods.specs)
    console.log('pathMap', pathMap)
    const btnClick = (value, values) => {
      // 当按钮禁用的时候直接return
      if (value.disabled) return
      // 点击时候 点击的那一个按钮
      console.log(value)
      // 可以动态添加一个selected属性,来通过判断这个属性的真假来绑定selected类名
      // 点击按钮的时候如果没有selected属性  就增加一个selected属性 并且赋值为true, 如果有属性,且属性值为true 那我们改成false
      if (value.selected) {
        value.selected = false
      } else {
        // 每一行只能选中一个 选的时候先给这一行所有的按钮selected属性变成false 再给选中的按钮selected属性变成true
        values.forEach(item => {
          item.selected = false
        })
        value.selected = true
      }
      updateDisabledStatus(pathMap, props.goods.specs)
      // 选中了所有按钮 就需要把数据传出去 通过判断当前选中的length 和传入的商品选项length是否相等
      const selectedArr = getSelectedSpec(props.goods.specs).filter(v => v)
      if (selectedArr.length === props.goods.specs.length) {
        const skuId = pathMap[selectedArr.join(spliter)][0]
        console.log('skuId', skuId)
        const sku = props.goods.skus.find(item => item.id === skuId)
        // 传递
        context.emit('change', {
          skuId: sku.id,
          price: sku.price,
          oldPrice: sku.oldPrice,
          inventory: sku.inventory,
          specsText: sku.specs.reduce((str, item) => `${str} ${item.name}：${item.valueName}`, '').trim('')
        })
      } else {
        context.emit('change', {})
      }
    }
    return {
      btnClick
    }
  }
}
</script>
<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
